/**
 * @file flash_test.c
 * @author your name (you@domain.com)
 * @brief
 * 该示例成功运行
 * 1. Flash的特性，写入前需要擦除，而且擦除是以页为单位的；
 * 2. VCT6的Flash大小256KB，Flash可能有128页，每页2KB；
 *
 * @version 0.1
 * @date 2025-02-24
 *
 * @copyright Copyright (c) 2025
 *
 */
#include <stdint.h>
#include <string.h>
#include "stm32f1xx_hal.h"
#include "flash_test.h"

/* STM32F103VCT6 高容量型号参数 */
#define FLASH_START_ADDR 0x08000000 // Flash起始地址
// #define FLASH_PAGE_SIZE 0x800                                                             // 2KB/页（高容量型号）
#define FLASH_TOTAL_PAGES 128                                                                // 256KB/2KB=128页
#define FLASH_USER_START_ADDR (FLASH_START_ADDR + (FLASH_TOTAL_PAGES - 1) * FLASH_PAGE_SIZE) // 0X0803F800 使用最后一页（页127）
#define FLASH_USER_END_ADDR (FLASH_USER_START_ADDR + FLASH_PAGE_SIZE)

// 测试数据（半字数组）
#define DATA_LENGTH 256
uint16_t writeData[DATA_LENGTH] = {0x1234, 0x5678, 0x9ABC, 0xDEF0};  // 示例数据
uint16_t writeData2[DATA_LENGTH] = {0x0101, 0x0202, 0x0303, 0x0404}; // 示例数据
uint16_t readData[DATA_LENGTH];

void flash_test(void)
{
    // Flash操作测试流程
    Flash_ErasePage(FLASH_USER_START_ADDR);                     // 擦除目标页
    Flash_Write(FLASH_USER_START_ADDR, writeData, DATA_LENGTH); // 写入数据
    Flash_Read(FLASH_USER_START_ADDR, readData, DATA_LENGTH);   // 读取数据

    // 数据验证（按字节比较）
    if (memcmp(writeData, readData, DATA_LENGTH * sizeof(uint16_t)) == 0)
    {
        // 验证成功（可添加指示灯）
    }
    else
    {
        // 验证失败（可添加错误处理）
    }
    Flash_Write(FLASH_USER_START_ADDR, writeData, DATA_LENGTH); // 写入数据
    Flash_Read(FLASH_USER_START_ADDR, readData, DATA_LENGTH);   // 读取数据
}

// 擦除指定地址所在的Flash页
void Flash_ErasePage(uint32_t pageAddress)
{
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0;

    // 解锁Flash操作
    HAL_FLASH_Unlock();

    // 配置擦除参数
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.PageAddress = pageAddress;
    EraseInitStruct.NbPages = 1; // 擦除1页

    // 执行擦除操作
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
    {
        // 错误处理（HAL_ERROR可获取具体错误码）
        //        Error_Handler();
    }

    // 重新锁定Flash
    HAL_FLASH_Lock();
}

// 写入数据到Flash（半字写入）
void Flash_Write(uint32_t address, uint16_t *data, uint32_t length)
{
    HAL_FLASH_Unlock();

    for (uint32_t i = 0; i < length; i++)
    {
        // 按半字写入，地址每次+2
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,
                              address + (i * 2),
                              data[i]) != HAL_OK)
        {
        }
    }

    HAL_FLASH_Lock();
}

// 从Flash读取数据
void Flash_Read(uint32_t address, uint16_t *data, uint32_t length)
{
    for (uint32_t i = 0; i < length; i++)
    {
        data[i] = *(__IO uint16_t *)(address + (i * 2));
    }
}
